#ifndef SIMPLEAPP5_H_
#define SIMPLEAPP5_H_

#include "CEGuiD3D10BaseApplication.h"

D3DXMATRIX                  g_World;
D3DXMATRIX                  g_View;
D3DXMATRIX                  g_Projection;


class SimpleApp: public CEGuiD3D10BaseApplication
{

    SubMesh sb[3];
public:

    void initMatrix()
    {
        // Initialize the world matrices
        D3DXMatrixIdentity( &g_World );

        // Initialize the view matrix
        D3DXVECTOR3 Eye( 0.0f, 4.0f, -10.0f );
        D3DXVECTOR3 At( 0.0f, 1.0f, 0.0f );
        D3DXVECTOR3 Up( 0.0f, 1.0f, 0.0f );
        D3DXMatrixLookAtLH( &g_View, &Eye, &At, &Up );

        RECT rc;
        GetClientRect( pimpl->d_window, &rc );
        UINT width = rc.right - rc.left;
        UINT height = rc.bottom - rc.top;

        // Initialize the projection matrix
        D3DXMatrixPerspectiveFovLH( &g_Projection, ( float )D3DX_PI * 0.25f, width / ( FLOAT )height, 0.1f, 100.0f );
    }

    HRESULT createScene()
    {        
        HRESULT hr = S_OK;

        bvRenderer = new BvD3D10Renderer(pimpl->d_device);
        ZeroMemory(sb, sizeof(sb));

        sb[0].eftId = bvRenderer->addEffect("Tutorial06.fx");
        sb[0].techName = "Render";

        D3D10_PASS_DESC PassDesc;
        bvRenderer->GetTechniquePassByIndexDesc(&PassDesc, sb[0].eftId, sb[0].techName, 0);

        FormatDesc fd[2] =
        {
            {0, TYPE_VERTEX, FORMAT_FLOAT, 3},
            {0, TYPE_NORMAL, FORMAT_FLOAT, 3},
        };
        sb[0].vfId = bvRenderer->addVertexFormat(fd, 2, &PassDesc);

        //create vertex buffer

        struct SimpleVertex
        {
            D3DXVECTOR3 Pos;
            D3DXVECTOR3 Normal;
        };

        // Create vertex buffer
        SimpleVertex vertices[] =
        {
            { D3DXVECTOR3( -1.0f, 1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) },
            { D3DXVECTOR3( 1.0f, 1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) },
            { D3DXVECTOR3( 1.0f, 1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) },
            { D3DXVECTOR3( -1.0f, 1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) },

            { D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, -1.0f, 0.0f ) },
            { D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, -1.0f, 0.0f ) },
            { D3DXVECTOR3( 1.0f, -1.0f, 1.0f ), D3DXVECTOR3( 0.0f, -1.0f, 0.0f ) },
            { D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR3( 0.0f, -1.0f, 0.0f ) },

            { D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR3( -1.0f, 0.0f, 0.0f ) },
            { D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR3( -1.0f, 0.0f, 0.0f ) },
            { D3DXVECTOR3( -1.0f, 1.0f, -1.0f ), D3DXVECTOR3( -1.0f, 0.0f, 0.0f ) },
            { D3DXVECTOR3( -1.0f, 1.0f, 1.0f ), D3DXVECTOR3( -1.0f, 0.0f, 0.0f ) },

            { D3DXVECTOR3( 1.0f, -1.0f, 1.0f ), D3DXVECTOR3( 1.0f, 0.0f, 0.0f ) },
            { D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 1.0f, 0.0f, 0.0f ) },
            { D3DXVECTOR3( 1.0f, 1.0f, -1.0f ), D3DXVECTOR3( 1.0f, 0.0f, 0.0f ) },
            { D3DXVECTOR3( 1.0f, 1.0f, 1.0f ), D3DXVECTOR3( 1.0f, 0.0f, 0.0f ) },

            { D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, -1.0f ) },
            { D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, -1.0f ) },
            { D3DXVECTOR3( 1.0f, 1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, -1.0f ) },
            { D3DXVECTOR3( -1.0f, 1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, -1.0f ) },

            { D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) },
            { D3DXVECTOR3( 1.0f, -1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) },
            { D3DXVECTOR3( 1.0f, 1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) },
            { D3DXVECTOR3( -1.0f, 1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) },
        };

        sb[0].vbId = bvRenderer->addVertexBuffer(vertices, sizeof(vertices));

        // Create index buffer
        DWORD indices[] =
        {
            3,1,0,
            2,1,3,

            6,4,5,
            7,4,6,

            11,9,8,
            10,9,11,

            14,12,13,
            15,12,14,

            19,17,16,
            18,17,19,

            22,20,21,
            23,20,22
        };
        uint nIndices = sizeof(indices)/sizeof(DWORD);
        sb[0].ibId = bvRenderer->addIndexBuffer(indices, sizeof(DWORD), nIndices);
        bvRenderer->setIndexBuffer(sb[0].ibId);

        bvRenderer->addSubMesh(sb[0]);

        initMatrix();

        sb[1] = sb[0];
        sb[1].techName = "RenderLight";
        sb[2] = sb[1];
        bvRenderer->addSubMesh(sb[1]);
        bvRenderer->addSubMesh(sb[2]);

        return hr;
    }

    void drawPerFrame()
    {
        // Update our time
        static float t = 0.0f;
        int g_driverType = 0;
        if( g_driverType == D3D10_DRIVER_TYPE_REFERENCE )
        {
            t += ( float )D3DX_PI * 0.0125f;
        }
        else
        {
            static DWORD dwTimeStart = 0;
            DWORD dwTimeCur = GetTickCount();
            if( dwTimeStart == 0 )
                dwTimeStart = dwTimeCur;
            t = ( dwTimeCur - dwTimeStart ) / 1000.0f;
        }

        // Rotate cube around the origin
        D3DXMatrixRotationY( &g_World, t );

        // Setup our lighting parameters
        D3DXVECTOR4 vLightDirs[2] =
        {
            D3DXVECTOR4( -0.577f, 0.577f, -0.577f, 1.0f ),
            D3DXVECTOR4( 0.0f, 0.0f, -1.0f, 1.0f ),
        };
        D3DXVECTOR4 vLightColors[2] =
        {
            D3DXVECTOR4( 0.5f, 0.5f, 0.5f, 1.0f ),
            D3DXVECTOR4( 0.5f, 0.0f, 0.0f, 1.0f )
        };

        //rotate the second light around the origin
        D3DXMATRIX mRotate;
        D3DXVECTOR4 vOutDir;
        D3DXMatrixRotationY( &mRotate, -2.0f * t );
        D3DXVec3Transform( &vLightDirs[1], ( D3DXVECTOR3* )&vLightDirs[1], &mRotate );

        bvRenderer->setEffectVariableByName(sb[0].eftId, "World", 
            EFFECT_VARIABLE_MATRIX, ( float* )&g_World);
        bvRenderer->setEffectVariableByName(sb[0].eftId, "View", 
            EFFECT_VARIABLE_MATRIX, ( float* )&g_View);
        bvRenderer->setEffectVariableByName(sb[0].eftId, "Projection", 
            EFFECT_VARIABLE_MATRIX, ( float* )&g_Projection);

        bvRenderer->setEffectVariableByName(sb[0].eftId, "vLightDir", 
            EFFECT_VARIABLE_VECTOR_FLOATARRAY, ( float* )vLightDirs, 0, 2);
        bvRenderer->setEffectVariableByName(sb[0].eftId, "vLightColor", 
            EFFECT_VARIABLE_VECTOR_FLOATARRAY, ( float* )vLightColors, 0, 2);
        
        bvRenderer->drawSubMesh(0, PRIM_TRIANGLES, 36, 0);

        for (int m = 0; m < 2; m++)
        {
            D3DXMATRIX mLight;
            D3DXMATRIX mLightScale;
            D3DXVECTOR3 vLightPos = vLightDirs[m] * 5.0f;
            D3DXMatrixTranslation( &mLight, vLightPos.x, vLightPos.y, vLightPos.z );
            D3DXMatrixScaling( &mLightScale, 0.2f, 0.2f, 0.2f );
            mLight = mLightScale * mLight;
            bvRenderer->setEffectVariableByName(sb[m+1].eftId, "World", 
                EFFECT_VARIABLE_MATRIX, (float*)&mLight);
            bvRenderer->setEffectVariableByName(sb[m+1].eftId, "vOutputColor", 
                EFFECT_VARIABLE_VECTOR_FLOAT, (float*)&vLightColors[m]);

            bvRenderer->drawSubMesh(m+1, PRIM_TRIANGLES, 36, 0);

        }

    }
};

#endif //SIMPLEAPP5_H_

